home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Information
/
CSMP Digest
/
volume 2
/
csmp-v2-006.txt
< prev
next >
Wrap
Text File
|
1995-06-30
|
44KB
|
1,228 lines
C.S.M.P. Digest Wed, 27 Jan 93 Volume 2 : Issue 6
Today's Topics:
Driving mac program from another
Detecting reboot or startup
Software control of landscape/not landscape
Preloading ALL code segments...?
The Comp.Sys.Mac.Programmer Digest is moderated by Michael A. Kelly.
The digest is a collection of article threads from the internet newsgroup
comp.sys.mac.programmer. It is designed for people who read c.s.m.p. semi-
regularly and want an archive of the discussions. If you don't know what a
newsgroup is, you probably don't have access to it. Ask your systems
administrator(s) for details. If you don't have access to news, there is
no way that I know of for you to post articles to the group.
Each issue of the digest contains one or more sets of articles (called
threads), with each set corresponding to a 'discussion' of a particular
subject. The articles are not edited; all articles included in this digest
are in their original posted form (as received by our news server at
cs.uoregon.edu). Article threads are not added to the digest until the last
article added to the thread is at least one month old (this is to ensure that
the thread is dead before adding it to the digest). Article threads that
consist of only one message are generally not included in the digest.
The entire digest is available for anonymous ftp from ftp.cs.uoregon.edu
[128.223.8.8] in the directory /pub/mac/csmp-digest. Be sure to read the
file /pub/mac/csmp-digest/README before downloading any files. The most
recent issues are available from sumex-aim.stanford.edu [36.44.0.6] in the
directory /info-mac/digest/csmp. If you don't have ftp capability, the sumex
archive has a mail server; send a message with the text '$MACarch help' (no
quotes) to LISTSERV@ricevm1.rice.edu for more information.
The digest is also available via email. Just send a note saying that you
want to be on the digest mailing list to mkelly@cs.uoregon.edu, and you will
automatically receive each new issue as it is created. Sorry, back issues
are not available through the mailing list.
Send administrative mail to mkelly@cs.uoregon.edu.
-------------------------------------------------------
From: ray@philmtl.philips.ca (Ray Dunn)
Subject: Driving mac program from another
Date: 18 Dec 92 04:14:29 GMT
Organization: Not Philips.
Question from someone fairly Mac illiterate but who has a serious need to
know:
Given a Mac program which normally takes much mouse events and keyboard
input, is it possible (easily/with difficulty) to have that program run
automatically with the input being generated by another program?
To save time, I'd appreciate an email answer, and will summarize replies
back to here.
Thanks.
- --
Ray Dunn at home | Beaconsfield, Quebec | Phone: (514) 630 3749
ray@philmtl.philips.ca | ray@cam.org | uunet!sobeco!philmtl!ray
+++++++++++++++++++++++++++
From: d88-jwa@dront.nada.kth.se (Jon Wtte)
Date: 18 Dec 92 17:50:34 GMT
Organization: Royal Institute of Technology, Stockholm, Sweden
In <1992Dec18.041429.22979@philmtl.philips.ca> ray@philmtl.philips.ca (Ray Dunn) writes:
>Given a Mac program which normally takes much mouse events and keyboard
>input, is it possible (easily/with difficulty) to have that program run
>automatically with the input being generated by another program?
Well, set "null events" on, and patch into the jGNEFilter. For
every NULL event, instead add your own keyDown events, with a nullEvent
sprinkled in here & yjere for good measure and recovery.
However, affecting someone elses jGNEFilter means patching in on
INIT time; so you'll have to have a cool INIT/APPL combo.
Cheers,
/ h+
- --
-- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe --
Engineering: "How will this work?" Science: "Why will this work?" Management:
"When will this work?" Liberal Arts: "Do you want fries with that?"
-- Jesse N. Schell
+++++++++++++++++++++++++++
From: absurd@apple.apple.com (Tim Dierks, software saboteur)
Date: Fri, 18 Dec 1992 22:23:37 GMT
Organization: MacDTS Marauders
In article <1992Dec18.175034.23523@kth.se>, d88-jwa@dront.nada.kth.se (Jon
Wtte) wrote:
> In <1992Dec18.041429.22979@philmtl.philips.ca> ray@philmtl.philips.ca (Ray Dunn) writes:
> However, affecting someone elses jGNEFilter means patching in on
> INIT time; so you'll have to have a cool INIT/APPL combo.
Actually, jGNEFilter is not (currently) swapped at process switch times;
if you change jGNEFilter in one app, you've changed it in all of them.
This makes life a little scary for jGNEFilter writers; if more than one
person patches this vector, the earlier ones are never allowed to go
away, because pointers to their code are stashed somewhere unknown.
Scary, huh?
Tim Dierks
MacDTS pinball addict (TM)
---------------------------
From: cmcclary@ucs.indiana.edu (Charles McClary)
Subject: Detecting reboot or startup
Date: 15 Dec 92 16:40:03 GMT
Organization: Indiana University
What is the best/preferred method for an application to detect if the
system has been rebooted or restarted since it (the application) last ran.
Thanks,
Charlie McClary
Indiana Univ.
cmcclary@indiana.edu
+++++++++++++++++++++++++++
From: steve.herman%express@freedom.msfc.nasa.gov (Steve Herman)
Date: 16 Dec 92 19:44:51 GMT
Organization: BCSS
In article <cmcclary-151292113831@mcclary-mac.ucs.indiana.edu>,
cmcclary@ucs.indiana.edu (Charles McClary) wrote:
>
> What is the best/preferred method for an application to detect if the
> system has been rebooted or restarted since it (the application) last ran.
>
At one time I had attempted to do this by doing the following:
1. Get the current time in seconds using GetDateTime()
2. Get number of ticks since last startup using TickCount()
3. Divide #2 by 60 to get seconds since startup.
4. Subtract #3 from #1 to get time in seconds of startup
5. Save this value to a file.
6. Whenever my application would startup it would perform steps 1-4 and
compare to the value stored in the file. If the values matched, plus or
minus a fudge factor I built in, then I would assume the machine had not
been re-booted since I last ran.
However, this would obviously break if the user changed the date/time on
his Mac. I also found out that TickCount is incremented during the
vertical retrace interrupt and whenever this interupt is disabled the ticks
are not incremented so it gradually loses time. On my particular machine it
was losing almost a minute for each hour my machine was up. This was going
to make my built-in fudge factor unrealistic.
I attempted to find another way to do this but eventually gave up. I
would like to know if you discover a reliable method.
- ----------------------------------------------------
- - Steve Herman - BCSS
- - Boeing Computer Support Services
- - Huntsville, AL
- ----------------------------------------------------
+++++++++++++++++++++++++++
From: d88-jwa@dront.nada.kth.se (Jon Wtte)
Date: 16 Dec 92 13:28:25 GMT
Organization: Royal Institute of Technology, Stockholm, Sweden
In <cmcclary-151292113831@mcclary-mac.ucs.indiana.edu> cmcclary@ucs.indiana.edu (Charles McClary) writes:
>What is the best/preferred method for an application to detect if the
>system has been rebooted or restarted since it (the application) last ran.
Install a gestalt selector with your own signature as selector code.
If it's there, the application run previously during this "session."
The selector code should reside in the system heap, and could simply
return a 0 as result; you would test for presence, not return code.
Cheers,
/ h+
- --
-- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe --
Nothing crashes like a Macintosh.
-- Guy Kawasaki
+++++++++++++++++++++++++++
From: kent@lloyd.Camex.COM (Kent Borg)
Organization: Camex Inc., Boston MA
Date: Thu, 17 Dec 1992 18:19:10 EST
In article <1992Dec16.132825.13170@kth.se> d88-jwa@dront.nada.kth.se (Jon Wtte) writes:
>In <cmcclary-151292113831@mcclary-mac.ucs.indiana.edu> cmcclary@ucs.indiana.edu (Charles McClary) writes:
>
>>What is the best/preferred method for an application to detect if the
>>system has been rebooted or restarted since it (the application) last ran.
>
>Install a gestalt selector with your own signature as selector code.
>
>If it's there, the application run previously during this "session."
>The selector code should reside in the system heap, and could simply
>return a 0 as result; you would test for presence, not return code.
I expected Jon to post that answer. He is right, do it that way.
However, if you want to run on old systems which don't have Gestalt,
there is another (related) approach.
Put a little something else in the System heap, note its location in a
file, and check whether it is still there when you next launch.
(Rather than using a file to record the address you might walk the
heap to find it. I doubt Apple will change the heap structure in
*old* systems.)
Off the top of my head, I can't remember how an app can allocate a
handle in the System heap and also prevent Multifinder from cleaning
up and deleting it for you when you exit, but loading a resource into
the System heap and then detaching it should work. Shouldn't it?
- --
Kent Borg kent@camex.com or kentborg@aol.com (when it is *working*)
H:(617) 776-6899 W:(617) 426-3577
As always, things look better when some costs are left out.
-Economist 3-28-92 p. 94
+++++++++++++++++++++++++++
From: tj@kona.cs.ucla.edu (Tom Johnson)
Date: 18 Dec 92 18:12:53 GMT
Organization: UCLA, Computer Science Department
cmcclary@ucs.indiana.edu (Charles McClary) asked:
>>
>>>What is the best/preferred method for an application to detect if the
>>>system has been rebooted or restarted since it (the application) last ran.
And d88-jwa@dront.nada.kth.se (Jon Wtte) answered:
>>
>>Install a gestalt selector with your own signature as selector code.
>>
In considering old systems that don't have Gestalt, kent@lloyd.Camex.COM
(Kent Borg) suggested:
>
>Put a little something else in the System heap, note its location in a
>file, and check whether it is still there when you next launch.
>(Rather than using a file to record the address you might walk the
>heap to find it. I doubt Apple will change the heap structure in
>*old* systems.)
>
>Off the top of my head, I can't remember how an app can allocate a
>handle in the System heap and also prevent Multifinder from cleaning
>up and deleting it for you when you exit, but loading a resource into
>the System heap and then detaching it should work. Shouldn't it?
>
This reminded me of how I used to handle communication between a cdev and
an INIT before Gestalt was available. I simply installed a small driver
and used it to pass variables back and forth.
For this purpose (detecting whether the machine has been rebooted, the
driver wouldn't really have to do anything - it could be a very simple
shell. As with Jon's Gestalt method, you would simply check for an error
- in this case one returned by OpenDriver().
Tom
- --
Tom Johnson "They say Confucious does his crossword with a pen."
tj@cs.ucla.edu -Tori Amos
+++++++++++++++++++++++++++
From: paul@taniwha.UUCP (Paul Campbell)
Date: 19 Dec 92 03:54:21 GMT
Organization: Taniwha Systems Design
In article <cmcclary-151292113831@mcclary-mac.ucs.indiana.edu> cmcclary@ucs.indiana.edu (Charles McClary) writes:
>What is the best/preferred method for an application to detect if the
>system has been rebooted or restarted since it (the application) last ran.
Assuming you saved the time your app last ran in a file and resource and
then read it back again into 'last_time_ran' then try:
unsigned long last_time_ran, now;
ReadDateTime(&now);
if ((now - (TickCount()/CLOCKS_PER_SEC)) > last_time_ran) {
// - we rebooted since last time we ran
}
Paul
- --
Paul Campbell UUCP: ..!mtxinu!taniwha!paul AppleLink: CAMPBELL.P
Use up your Quayle jokes now while they're still good "Quayle for Pres. in '94"
Q: Why is Marilyn Quayle like Marion Barry?
A: They both suck a little dope.
---------------------------
From: bowman@reed.edu (Mr. Stress Tensor)
Subject: Software control of landscape/not landscape
Date: 18 Dec 92 20:51:37 GMT
Organization: Reed College, Portland, OR
What's the best way to force landscape printing? It would be nice if PrGeneral
would do it, but apparently it can't (?). I'd love to be wrong about that.
It seems a bad idea to mucking directly into the print record, since I certainly
can't test on every printer there is. It also seems like it might be possible
to fake a mousedown in the Page Setup dialog so that it defaults to landscape,
but I'd like, if possible, to be able to use the print record for various
nefarious porpoises.
Thanks,
bobo In seeking the unattainable,
bowman@reed.edu simplicity only gets in the way.
Ask not what's inside your head but what your head's inside of. - W. Mace
+++++++++++++++++++++++++++
From: engber@ils.nwu.edu (Mike Engber)
Date: 22 Dec 92 14:51:06 GMT
Organization: The Institute for the Learning Sciences
Attached is the relevant code extracted from SaveATree. It's THINK C code.
Basically, there is no official way to get a landscape print record,
but it's somewhat common knowledge that the orientation is controlled
by single bit in the print record (once source for this info is
MacRevealed vol 3). This bit is used for Apple printers and deskwriters
- - don't have access to other types of printers to check it out.
My conservative approach is to:
1) flip the bit
2) use PrValidate to make sure I didn't trash the print record - i.e.
this driver can't handle this bit being flipped.
3) use PrGeneral to make sure flipping the bit put the print record
into landscape mode (instead of doing something else)
4) if 1-3 didn't work, I prompt the user to pick a landscape record
from the PrStlDialog I subsequently display. This is sure to work
unless the user screws up (I display the landscape Icon in the dialog
in an attempt to make it more foolproof).
5) Once I get a landscape record I save it away so I'll never have
to do this again.
This should work pretty well. I don't think it violate any guidlines
(too badly). And I've never had and problems reported wrt to SaveATree
doing it. Some cavats:
1) the printer must have PrGeneral implemented along with the getRotnOp
opcode (I assume most do nowadays)
2) Older HP deswriter drivers have PrGeneral & getRotnOp implementd, but
don't return a success error code from PrGeneral. So flipping the bit
works, but since PrGeneral says it's didn't - I end up prompting the
user anyway. This bug has been fixed in the more recent drivers.
- -ME
- ---
void PrintPromptedStyle(THPrint printRecH, Boolean landscape){
Alert(DU_CenterALRT(landscape ? L_SETUP_ALERT_ID : P_SETUP_ALERT_ID),0L);
PrOpen();
PrStlDialog(printRecH);
PrClose();
}
static Boolean PrRotn(THPrint printRecH, Boolean* landscape){
TGetRotnBlk rotnBlk;
rotnBlk.iOpCode = getRotnOp;
rotnBlk.hPrint = printRecH;
PrGeneral((Ptr)&rotnBlk);
if(rotnBlk.iError == noErr){
*landscape = rotnBlk.fLandscape ? true : false;
return true;
}else{
return false;
}
}
void PrintDefaultRotn(THPrint printRecH, Boolean landscape){
Boolean is_landscape;
static TPrint landscapeTPrint;
static TPrint portraitTPrint;
static Boolean landscapeStored = false;
static Boolean portraitStored = false;
PrOpen();
if(PrintError("\pprint.c: PrintDefaultRotn()","\pPrOpen") != noErr){
PrClose();
return;
}
PrValidate(printRecH);
if(PrRotn(printRecH,&is_landscape)){
if(is_landscape != landscape){
/* toggle the bit */
(*printRecH)->prStl.wDev ^= 0x02;
/* make sure it worked */
PrValidate(printRecH);
if(PrRotn(printRecH,&is_landscape) && is_landscape==landscape){
PrClose();
return;
}
}else{
/* it was ok to begin with */
PrClose();
return;
}
}
/*
If we reach this point either PrGeneral/getRotnOp or the
bit toggling won't work on this printer. So we'll prompt
the user & display a style dlog (ugh!).
*/
PrClose();
if(landscape){
if(landscapeStored){
**printRecH = landscapeTPrint;
}else{
PrintPromptedStyle(printRecH,landscape);
landscapeStored = true;
landscapeTPrint = **printRecH;
}
}else{
if(portraitStored){
**printRecH = portraitTPrint;
}else{
PrintPromptedStyle(printRecH,landscape);
portraitStored = true;
portraitTPrint = **printRecH;
}
}
}
---------------------------
From: hanord@rubin.dbe (Haavard Nord)
Subject: Preloading ALL code segments...?
Date: 1 Dec 92 18:43:46 GMT
Organization: Department of Biomedical Engineering
Maybe this is a common question, but I hope someone can help me anyway.
I have a faceless background application that communicates with a client
(external 4D procedure) via PPC. The background application uses asynch
PPC services, i.e. its completion routines are some sort of interrupt.
When such an interrupt is invoked, the mac thinks that the foreground
application is still current. When the background application makes calls
to procedures in other CODE segments, the segment loader isn't able to
load anything for the background. I've tried setting the global CurMap
variable with UseResFile(), but it does nothing.
The solution is to have all code segments preloaded. How can I do this?
There are more than 30 segments, and some of these come from library
files. I could use the '-sn myseg=Main' option with Link, but that
requires that I know all segments, and the number of segments may change
when the program is modified.
Another solution is to initially make calls to all functions I intend to
use from the interrupt procedure, but that is as stupid as using -sn.
So --- what can I do? How can I (easily) load all segments at once when
the background application starts, or how can I use UseResFile()?
Thanks,
- -hanord
- --
===============================================================================
Haavard Nord email: hanord@ibt.unit.no
Dept. of Biomedical Engineering phone: +47 7 598685
Trondheim, Norway fax: +47 7 598613
===============================================================================
+++++++++++++++++++++++++++
Organization: Royal Institute of Technology, Stockholm, Sweden
Date: Tue, 1 Dec 1992 19:29:55 GMT
In <HANORD.92Dec1194346@rubin.dbe> hanord@rubin.dbe (Haavard Nord) writes:
>The solution is to have all code segments preloaded. How can I do this?
>There are more than 30 segments, and some of these come from library
>files. I could use the '-sn myseg=Main' option with Link, but that
>requires that I know all segments, and the number of segments may change
>when the program is modified.
>Another solution is to initially make calls to all functions I intend to
>use from the interrupt procedure, but that is as stupid as using -sn.
>So --- what can I do? How can I (easily) load all segments at once when
>the background application starts, or how can I use UseResFile()?
You, of course, cannot load resources under interrupt time, since
you can do NOTHING that would move memory, and loading resources
or calling across boundaries certainly do.
Now, what do you want to do in an interrupt service routine that
would be so complicated as to require intra-segment calls? That would
probably take time, and time during interrupt handling is CRITICAL!
The mac is COMPLETELY FROZEN during interrupt servicing, and you
don't want to be cruel to your users, right?
What you should do, is pre-allocate what buffers you need, and
store whatever data comes in there, and set a flag that your main
event loop will see next time through, and THEN do whatever you
want to do. This is the only safe & fair way of doing "it."
If you have to pre-load all code resources, just do a simple:
void
PreLoadAllCode ( void )
{
Handle h ;
int i ;
SetResLoad ( 0 ) ;
for ( i = Count1Resources ( 'CODE' ) ; i > 0 ; i -- ) {
h = Get1IndResource ( 'CODE' , i ) ;
if ( * h ) {
HLock ( h ) ;
} else {
LoadResource ( h ) ;
if ( ResError ( ) ) {
SetResLoad ( 1 ) ;
FailHorribly ( ResError ( ) ) ;
} else {
HUnlock ( h ) ;
MoveHHi ( h ) ;
HLock ( h ) ;
}
}
}
SetResLoad ( 1 ) ;
}
But, as I said, since you can call virtually NO toolbox traps
either directly or indirectly during interrupt time; don't.
And without calling the toolbox, there's not much more you can
do but set a flag, and maybe queue a pre-prepared reply.
Cheers,
/ h+
- --
-- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe --
"From now on I will re-label the EQ on the deck as Fizz and Wobble
instead of HF and LF."
+++++++++++++++++++++++++++
From: ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University)
Date: 2 Dec 92 09:07:54 +1300
Organization: University of Waikato, Hamilton, New Zealand
In article <HANORD.92Dec1194346@rubin.dbe>, hanord@rubin.dbe (Haavard Nord) writes:
> Maybe this is a common question, but I hope someone can help me anyway.
>
> I have a faceless background application that communicates with a client
> (external 4D procedure) via PPC. The background application uses asynch
> PPC services, i.e. its completion routines are some sort of interrupt.
>
> When such an interrupt is invoked, the mac thinks that the foreground
> application is still current. When the background application makes calls
> to procedures in other CODE segments, the segment loader isn't able to
> load anything for the background. I've tried setting the global CurMap
> variable with UseResFile(), but it does nothing.
Remember that loading code segments means allocating memory, which means
you can't do it at interrupt time.
> The solution is to have all code segments preloaded.
This is the right idea.
> How can I do this?
> There are more than 30 segments, and some of these come from library
> files. I could use the '-sn myseg=Main' option with Link, but that
> requires that I know all segments, and the number of segments may change
> when the program is modified.
There's another directive , '-sg', which, among other things, takes the
segment names in the opposite order to '-sn'. If you just use it in a form like
-sg Everything
then *all* your code gets put into a single segment called "Everything".
This is probably the simplest solution, if your program isn't too large.
> Another solution is to initially make calls to all functions I intend to
> use from the interrupt procedure, but that is as stupid as using -sn.
It may be clumsy, but in many cases it's the only way. What you actually have
to do is make a call to one routine in every *segment* that contains routines
that might be used by your interrupt code. You could add a dummy routine to
each such segment, specifically for this purpose.
This means you have to keep careful track of the segments in your program.
But do you really need over 30 of them? You're probably better off merging
a few of them with -sn or -sg directives.
Lawrence D'Oliveiro fone: +64-7-856-2889
Computer Services Dept fax: +64-7-838-4066
University of Waikato electric mail: ldo@waikato.ac.nz
Hamilton, New Zealand 37^ 47' 26" S, 175^ 19' 7" E, GMT+13:00
+++++++++++++++++++++++++++
From: keith@taligent.com (Keith Rollin)
Organization: Taligent
Date: Tue, 1 Dec 1992 21:14:23 GMT
In article <HANORD.92Dec1194346@rubin.dbe>, hanord@rubin.dbe (Haavard Nord)
wrote:
>
> The solution is to have all code segments preloaded. How can I do this?
> There are more than 30 segments, and some of these come from library
> files.
int i;
for (i = 0; i < kNumberOfSegs; ++i)
LoadSeg(i);
- -----
Keith Rollin
Phantom Programmer
Taligent, Inc.
+++++++++++++++++++++++++++
From: ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University)
Date: 2 Dec 92 17:32:50 +1300
Organization: University of Waikato, Hamilton, New Zealand
tte) writes:
>
> If you have to pre-load all code resources, just do a simple:
>
> void
> PreLoadAllCode ( void )
> {
> Handle h ;
> int i ;
>
> SetResLoad ( 0 ) ;
>
> for ( i = Count1Resources ( 'CODE' ) ; i > 0 ; i -- ) {
>
> h = Get1IndResource ( 'CODE' , i ) ;
> if ( * h ) {
>
> HLock ( h ) ;
>
> } else {
>
> LoadResource ( h ) ;
> if ( ResError ( ) ) {
>
> SetResLoad ( 1 ) ;
> FailHorribly ( ResError ( ) ) ;
>
> } else {
>
> HUnlock ( h ) ;
> MoveHHi ( h ) ;
> HLock ( h ) ;
> }
> }
> }
>
> SetResLoad ( 1 ) ;
> }
This routine isn't going to help. It's just a way of doing at run time
what you can do at link time by specifying "-ra =preload". Sure, the CODE
resources will all be in memory, but the jump tables aren't going to be
set up. The segment loader will still make its own Resource Manager calls
to find those segments, which will mean traversing resource maps, which is
not going to work very nicely at interrupt time.
Lawrence D'Oliveiro fone: +64-7-856-2889
Computer Services Dept fax: +64-7-838-4066
University of Waikato electric mail: ldo@waikato.ac.nz
Hamilton, New Zealand 37^ 47' 26" S, 175^ 19' 7" E, GMT+13:00
+++++++++++++++++++++++++++
From: absurd@apple.apple.com (Tim Dierks, software saboteur)
Date: Wed, 2 Dec 1992 07:48:39 GMT
Organization: MacDTS Marauders
In article <keith-011292131150@kip-15.taligent.com>, keith@taligent.com
(Keith Rollin) wrote:
>
> In article <HANORD.92Dec1194346@rubin.dbe>, hanord@rubin.dbe (Haavard Nord)
> wrote:
> >
> > The solution is to have all code segments preloaded. How can I do this?
> > There are more than 30 segments, and some of these come from library
> > files.
>
> int i;
> for (i = 0; i < kNumberOfSegs; ++i)
> LoadSeg(i);
>
> -----
> Keith Rollin
> Phantom Programmer
> Taligent, Inc.
I really hate to contradict Mr. Rollin, because there's a certain
lurking suspicion that I could be incorrect, but this won't help
for 3 reasons: first, LoadSeg is a very special trap; it requires
that the code that calls it be structured in a particular way:
first, the offset, hard coded as a constant into the code (2 bytes),
then an instruction which loads the segment number onto the stack
(4 bytes) and the LoadSeg trap (2 bytes). All this makes a jump
table entry, and is described and depicted on page 61 of Inside
Mac II. Second, LoadSeg never returns, because it's intended only
as a mechanism for dispatching to routines in unloaded segments;
this will cause this loop to never get to its second iteration.
Third, due to these limitations, there isn't any prototype for
LoadSeg; as far as I know, it can't be called from C or Pascal
without writing your own prototype (and then would be very
difficult to call correctly).
Tim Dierks
Speaking solely for himself
+++++++++++++++++++++++++++
From: scott@phylo.life.uiuc.edu (Scott Howard)
Date: 2 Dec 92 15:05:11 GMT
Organization: University of Illinois at Urbana
This seems to be too simple to work, but how about
Using ResEdit to Flag all your code Resources as Pre-Load
and No-Purge?
- --
Coffee Facts from Dr. Science:
1) You can never brew coffee too strong.
2) You can never drink too much coffee.
3) Coffee does not make you nervous. Your own inadequacies do that.
Coffee merely increases your perception of your own inadequacies.
4) Tea is to coffee as ginger ale is to Scotch.
+++++++++++++++++++++++++++
From: keith@taligent.com (Keith Rollin)
Date: 2 Dec 92 20:50:17 GMT
Organization: Taligent
In article <absurd-011292234220@seuss.apple.com>, absurd@apple.apple.com
(Tim Dierks, software saboteur) wrote:
>
> In article <keith-011292131150@kip-15.taligent.com>, keith@taligent.com
> (Keith Rollin) wrote:
> >
> > In article <HANORD.92Dec1194346@rubin.dbe>, hanord@rubin.dbe (Haavard Nord)
> > wrote:
> > >
> > > The solution is to have all code segments preloaded. How can I do this?
> > > There are more than 30 segments, and some of these come from library
> > > files.
> >
> > int i;
> > for (i = 0; i < kNumberOfSegs; ++i)
> > LoadSeg(i);
>
> I really hate to contradict Mr. Rollin, because there's a certain
> lurking suspicion that I could be incorrect, but this won't help
> for 3 reasons: first, LoadSeg is a very special trap; it requires
> that the code that calls it be structured in a particular way:
> first, the offset, hard coded as a constant into the code (2 bytes),
> then an instruction which loads the segment number onto the stack
> (4 bytes) and the LoadSeg trap (2 bytes). All this makes a jump
> table entry, and is described and depicted on page 61 of Inside
> Mac II. Second, LoadSeg never returns, because it's intended only
> as a mechanism for dispatching to routines in unloaded segments;
> this will cause this loop to never get to its second iteration.
> Third, due to these limitations, there isn't any prototype for
> LoadSeg; as far as I know, it can't be called from C or Pascal
> without writing your own prototype (and then would be very
> difficult to call correctly).
I really hate to not contradict Mr. Dierks, but he's right. I was tricked
into thinking that LoadSeg could be called by the THINK Reference. Although
it the reference does say "LoadSeg is called indirectly...", it didn't jump
out and say that one CAN'T call it directly. It also gave a high-level
interface to the call. If I'd given the answer 2 seconds of thought before
sending it, I'd've realized that you couldn't call LoadSeg.
Well, I guess I'm in good company for being wrong today. Lawrence just
caught Jon in a boo-boo, too.
Calling a dummy function in each segment would be a way to go, but that's
not fun. How about using a function loosely based on MacApp's
PreLoadSegment function? First get the address of _LoadSeg with
GetTrapAddress. Then call the following function instead of LoadSeg, like I
showed above.
EXPORT PROCEDURE RETURNABLELOADSEG(theSegNum:W)
BEGIN Save=D0-D2/A0-A2
IMPORT LOADSEGADDRESS
MOVE LOADSEGADDRESS(A5),A0
Move.W theSegNum(FP),-(SP) ; push the original parameter to loadseg
PEA ComeBack+6 ; push a return address
; loadseg will knock 6 off the return
address
Jmp (A0) ; Call the original loadseg
ComeBack
Return ; Return to the real world
EndP
- -----
Keith Rollin
Phantom Programmer
Taligent, Inc.
+++++++++++++++++++++++++++
From: werner@soe.berkeley.edu (John Werner)
Date: 2 Dec 1992 22:16:00 GMT
Organization: UC Berkeley School of Education
In article <absurd-011292234220@seuss.apple.com>, Tim Dierks wrote:
> In article <keith-011292131150@kip-15.taligent.com>, Keith Rollin:
> > int i;
> > for (i = 0; i < kNumberOfSegs; ++i)
> > LoadSeg(i);
> >
>
> I really hate to contradict Mr. Rollin, because there's a certain
> lurking suspicion that I could be incorrect, but this won't help
> for 3 reasons: first, LoadSeg is a very special trap
How about something like this:
short num = Count1Resources('CODE');
for (short i = 1; i <= num; i)) {
Handle hdl = Get1IndResource('CODE', I);
HLock(hdl);
HNoPurge(hdl);
}
This should get all the segments into memory. It won't change the jump
table to say that they're already loaded. But LoadSeg will take care of
that (without moving memory) the first time a function in each segment is
called, so it shouldn't matter.
[By the way, the article I'm following up to had a bogus distrution "comp".
I changed it to "world.]
- --
John Werner werner@soe.berkeley.edu
UC Berkeley School of Education 510-642-9651
+++++++++++++++++++++++++++
From: bowman@reed.edu (BoBoRamDos)
Date: 2 Dec 92 23:22:40 GMT
Organization: Reed College, Portland, OR
So, can you recover if RETURNABLELOADSEG fails? That could be mighty handy,
a bit easier than maintaining a separate heap for code segs, at least sometimes.
Especially since SADE has a tendency to get very confused when doing that.
cheers,
bobo In seeking the unattainable,
bowman@reed.edu simplicity only gets in the way.
Ask not what's inside your head but what your head's inside of. - W. Mace
+++++++++++++++++++++++++++
From: keith@taligent.com (Keith Rollin)
Organization: Taligent
Date: Thu, 3 Dec 1992 01:23:49 GMT
In article <1992Dec2.232240.3040@reed.edu>, bowman@reed.edu (BoBoRamDos)
wrote:
>
>So, can you recover if RETURNABLELOADSEG fails? That could be mighty handy,
>a bit easier than maintaining a separate heap for code segs, at least sometimes.
>Especially since SADE has a tendency to get very confused when doing that.
Aw, you would bring that up. One thing that you could do have
RETURNABLELOADSEG call GetResource for the CODE segment you are interested
in. If that fails, then RETURNABLELOADSEG returns FALSE. If the CODE
segment loads, then call LoadSeg and return TRUE. MacApp's version does
this; I just didn't show it in my posting.
- -----
Keith Rollin
Phantom Programmer
Taligent, Inc.
+++++++++++++++++++++++++++
From: keith@taligent.com (Keith Rollin)
Organization: Taligent
Date: Thu, 3 Dec 1992 01:27:20 GMT
In article <werner-021292141545@128.32.157.31>, werner@soe.berkeley.edu
(John Werner) wrote:
>
> How about something like this:
>
> short num = Count1Resources('CODE');
> for (short i = 1; i <= num; i)) {
> Handle hdl = Get1IndResource('CODE', I);
> HLock(hdl);
> HNoPurge(hdl);
> }
>
> This should get all the segments into memory. It won't change the jump
> table to say that they're already loaded. But LoadSeg will take care of
> that (without moving memory) the first time a function in each segment is
> called, so it shouldn't matter.
As Lawrence pointed out, the problem with this is that LoadSeg will *still*
call GetResource. This would require that the proper resource chain be
swapped in. However, that's not the case under the circumstances of the
original poster's question.
By the way, you'd probably want a MoveHHi() in there before the HLock().
Better yet, use HLockHi(). And if the handle's locked, you don't need the
call to HNoPurge().
- -----
Keith Rollin
Phantom Programmer
Taligent, Inc.
+++++++++++++++++++++++++++
Organization: Royal Institute of Technology, Stockholm, Sweden
Date: Thu, 3 Dec 1992 12:24:18 GMT
In <1992Dec2.173250.12571@waikato.ac.nz> ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) writes:
>This routine isn't going to help. It's just a way of doing at run time
Well, no. Actually, yes, it will help prevent spinning the disk
re right about it not changing the jump
tables. For that you could include a function in each and every
segment that got called on startup to load the segment.
OR: (Hack warning) You could walk the jump table and patch it up yourself.
s not too hard actually, as long as you make sure to flush the cache.
- --
-- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe --
"From now on I will re-label the EQ on the deck as Fizz and Wobble
instead of HF and LF."
+++++++++++++++++++++++++++
From: bobert@informix.com (Robert Murphy)
Date: 3 Dec 92 00:49:33 GMT
Organization: Informix Software, Inc.
Haavard Nord started this thread by talking about problems he is having in
an interrupt-time completion routine. It calls code in another code segment
which may not be loaded, and this seems to cause all kinds of trouble which
he hoped to avoid by preloading all his code segments. A number of people
have made suggestions about how to do this and how you shouldn't try to load
code segments at interrupt time (it does the evil deed of moving memory).
Having just been thrashing with PPC completion routines, I'd make one more
remark. If you're going to call a routine outside the current code segment
at interrupt time, *** MAKE SURE YOUR A5 WORLD IS SET UP CORRECTLY *** !!!!!
Otherwise, you will probably be calling code in some other app, and Gopod
help you if you try to use access any global or static variables. For more
info on screwing around with A5 worlds in a completion routine, see IM VI
p. 28-14, and also Tech Note #256, which has a really great discussion of
A5 worlds in general and why you would want to worry about them.
Bob Murphy
+++++++++++++++++++++++++++
From: ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University)
Date: 4 Dec 92 11:17:42 +1300
Organization: University of Waikato, Hamilton, New Zealand
tte) writes:
> In <1992Dec2.173250.12571@waikato.ac.nz> ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) writes:
>
>>This routine isn't going to help. It's just a way of doing at run time
>
> Well, no. Actually, yes, it will help prevent spinning the disk
> for PowerBook users...
Something else I thought of: I remember a tech note that appeared when the
Mac Plus first came out. It described a special "fast load" mode in the
Resource Manager, whereby (if I recall correctly) if you had a bunch of
preloadable resources stored contiguously in a resource file, they would be
read into memory with some minimum number of disk reads when the file was
opened.
Somehow this information never made it into Inside Mac. Is it still true? If
so, it's another advantage of specifying the preload bit over Jon's run-time
solution. :-)
Lawrence D'Oliveiro fone: +64-7-856-2889
Computer Services Dept fax: +64-7-838-4066
University of Waikato electric mail: ldo@waikato.ac.nz
Hamilton, New Zealand 37^ 47' 26" S, 175^ 19' 7" E, GMT+13:00
+++++++++++++++++++++++++++
From: anadig@otago.ac.nz
Date: 8 Dec 92 08:39:27 GMT
Organization: University of Otago, Dunedin, New Zealand
In article <1992Dec4.111742.12613@waikato.ac.nz>, ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) writes:
> Something else I thought of: I remember a tech note that appeared when the
> Mac Plus first came out. It described a special "fast load" mode in the
> Resource Manager, whereby (if I recall correctly) if you had a bunch of
> preloadable resources stored contiguously in a resource file, they would be
> read into memory with some minimum number of disk reads when the file was
> opened.
I think you are thinking of JumpStart: not so much a tech note as a utility. It
rearranged your resource fork so that things were in the order that they
loaded, using a log that it acquired with another tool. Cute idea: I remember
that it had a few dangerous modes in which it would relocate the resource map
and do a few semi-legal things as well. It certainly sped up application
startup from floppies.
The simpler thing that you can do yourself - and UpdateMaker actually does it
:-) - is write out all the preloaded resources first when you are building an
application. As a result applications updated with UpdateMaker may actually
start up a little bit quicker than the original...
Michael(tm) Hamel
Analog Digital Instruments, Dunedin, New Zealand.
+++++++++++++++++++++++++++
From: milton@ccu.umanitoba.ca (Dave Milton)
Date: 7 Dec 92 17:59:57 GMT
Organization: University of Manitoba, Winnipeg, Canada
One way to force loading of all segments is to place a simple routine
which does nothing into each segment. For argument sake you could call
this ForceName where the Name is the name of the segment; you could
also use the segment number. At application startup time you can then
force all of these segments to load by calling all of those routines.
For example, if you have one segment called printing, a second called
search, and a third called connect then you could place into your init
segment a routine
void ForceLoadSeg()
{
ForcePrinting();
ForceSearch();
ForceConnect();
}
Each code segment would contain a routine that does nothing:
void ForcePrinting() {} // or ForceSearch or ForceConnect
Doing something like the above will cause all modules to load. Since I
came in at the middle of this thread I may have missed the purpose of
loading all the code modules at one time. I do have a misgiving about
doing this kind of thing: it defeats the entire purpose of having a
program broken into segments. I am under the impression that having
seperate code segments will reduce the memory footprint of your program.
A properly segmented program will use much less memory during normal
operations than a program that simply loads all its segments when it
starts up. This technique may be useful for testing whether your program
works well under low memory conditions but beyond that its value is
dubious IMHO.
Hope this helps
- --
David Milton, University of Manitoba, Winnipeg, Canada. (204)788-6346
Internet: milton@ccu.UManitoba.CA Bitnet: milton@UOFMCC
+++++++++++++++++++++++++++
From: scott@mcl.ucsb.edu (Scott Bronson)
Date: 11 Dec 92 02:37:17 GMT
In <BywHzy.4C9@ccu.umanitoba.ca> milton@ccu.umanitoba.ca (Dave Milton) writes:
>One way to force loading of all segments is to place a simple routine
>o load by calling all of those routines.
>For example, if you have one segment called printing, a second called
>search, and a third called connect then you could place into your init
>segment a routine
> void ForceLoadSeg()
> {
> ForcePrinting();
> ForceSearch();
> ForceConnect();
> }
>Each code segment would contain a routine that does nothing:
> void ForcePrinting() {} // or ForceSearch or ForceConnect
A tiny little thought...
In the (perhaps paranoid) fear that some smart C compiler would
label my functions as dead code and strip them and calls to them
(after all, they are optimizing a needless segment load out, quite
a good optimization IMHO), I simply split my InitMacintosh routine
into my segments:
void InitMacintosh()
{
InitGraf, InitFonts, InitWindows...
InitPrinting();
InitSearch();
InitConnect();
}
Told ya it was insignificant; I thought it was cool...
+++++++++++++++++++++++++++
From: thomas@camino.mic.cl (Thomas Fruin)
Date: 27 Dec 92 00:55:22 GMT
Organization: El Camino
In article <keith-021292172408@kip-15.taligent.com> (comp.sys.mac.programmer),
keith@taligent.com (Keith Rollin) writes:
>By the way, you'd probably want a MoveHHi() in there before the HLock().
>Better yet, use HLockHi(). And if the handle's locked, you don't need the
>call to HNoPurge().
>
>-----
>Keith Rollin
>Phantom Programmer
>Taligent, Inc.
Hey, what is HLockHi()? I can guess what it does, but I have never seen it
documented anywhere. Is it MPW glue or a real trap?
- -- Thomas Fruin
thomas@camino.mic.cl
+++++++++++++++++++++++++++
From: d88-jwa@dront.nada.kth.se (Jon Wtte)
Date: 27 Dec 92 09:46:37 GMT
Organization: Royal Institute of Technology, Stockholm, Sweden
In <0105013E.m27dq5@camino.mic.cl> thomas@camino.mic.cl (Thomas Fruin) writes:
>Hey, what is HLockHi()? I can guess what it does, but I have never seen it
>documented anywhere. Is it MPW glue or a real trap?
It's glue taking advantage of the passing conventions for
handle traps to optimize stack and register usage (i.e.
don't have to adjust stack or reload registers between
the traps)
And it's not only in MPW.
Cheers,
/ h+
- --
-- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe --
Engineering: "How will this work?" Science: "Why will this work?" Management:
"When will this work?" Liberal Arts: "Do you want fries with that?"
-- Jesse N. Schell
---------------------------
End of C.S.M.P. Digest
**********************